package interfaze;

import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

import logic.EarthDefenderConfig;
import logic.EarthDefenderGameThread;
import logic.EarthDefenderLevelFiller;
import logic.NoSaveException;
import logic.Utilities;

import entities.Defender;
import entities.Enemy;
import entities.Level;
import entities.Life;
import entities.Score;

@SuppressWarnings("serial")
public class SpaceInvadersGamingPanel extends JPanel implements KeyListener, FocusListener{
	
	public SuperArcade2in1 window;
	public Life lives;
	public Level level;
	public Score points;
	private float xScale;
	private float yScale;
	private JLabel background = new JLabel();
	private int velEnem=100;
	private int velEnemY=50;
	private Defender def;
	private boolean tRunning=false;
	EarthDefenderGameThread edThread;
	private boolean apressed;
	private boolean dpressed;
	
	private Font font;
	
	/**
	 * creates the panel with the necessary components (life, score and level display as well as background) and then starts the game
	 * @param window
	 */
	public SpaceInvadersGamingPanel(SuperArcade2in1 window) {
		this.window = window;
		this.setLayout(null);
		xScale = window.xScale;
		yScale = window.yScale;
		this.setFocusable(true);
		this.requestFocus();
		
		font = new Font("Helvetica", Font.PLAIN, Math.round(12 * window.xScale));
		
		
		Image image = Utilities.loadImage("res/EarthDefenderBackground.png");
		if(window.xScale != 1 || window.yScale != 1) {
			image = Utilities.resizeImage(window.xScale, window.yScale, "res/EarthDefenderBackground.png");
		}
		background.setIcon(new ImageIcon(image));
		background.setBounds(0, 0, window.width, window.height);
		this.add(background,-1);
		background.setVisible(true);
		
		this.setBackground(Color.black);
	
		setEntities();
		
		addComponents();
		
		
		this.addKeyListener(this);
		this.addFocusListener(this);
		startgame();
	}
	/**
	 * sets some entities necessary for the information to be properly displayed to the user
	 */
	private void setEntities() {

		lives = new Life(window.width - Life.getWidth(window.xScale), 
				window.height - (Life.getHeight(window.yScale) + 25), window.xScale, window.yScale);
		lives.setFont(font);
		
		level = new Level(window.width - (Level.getWidth(window.xScale) + Math.round(5 * window.xScale)),
				Math.round(5 * window.yScale), window.xScale, window.yScale);
		level.setFont(font);
		
		points = new Score(Math.round(5 * window.xScale), Math.round(5 * window.yScale), window.xScale, window.yScale);
		points.setFont(font);}
		
	/**
	 * adds the components necessary to properly display gameplay information to the panel
	 */
	private void addComponents() {
		this.add(lives, 0);
		this.add(points, 0);
		this.add(level, 0);
	}

	@Override
	public void keyTyped(KeyEvent e) {
		
	}

	@Override
	/**
	 * handles the escape (quit game), A and D (movement) and space (shooting) keyboard events, the same goes for the keyreleased method below
	 */
	public void keyPressed(KeyEvent e) {
		if(tRunning){
			/**
			 * the horizontal speed of the defender is changed to make it move left as long as the button 'A' is pressed
			 */
		if(e.getKeyCode() == KeyEvent.VK_A) {
			def.setDX(-200);
			apressed=true;
			/**
			 * the horizontal speed of the defender is changed to make it move right as long as the button 'D' is pressed
			 */
		} else if(e.getKeyCode() == KeyEvent.VK_D) {
			def.setDX(200);
			dpressed=true;
			/**
			 * changes the value of a flag in the EarthDefenderGameThread class, its purpose is properly explained inside it
			 */
		} else if(e.getKeyCode() == KeyEvent.VK_SPACE) {
			edThread.defShot=true;
		}
		}
		/**
		 * this if will create and start the thread necessary when the player hits enter, assuming the thread isn't already running
		 * in which case, nothing will happen
		 */
	}
	/**
	 * starts the thread responsible for the game management
	 */
	private void startgame(){
		ArrayList<Object> config=null;
		/**
		 * the code tries to retrieve the user's desired configuration.
		 */
		try {
			config = EarthDefenderConfig.load(window.userName);
			
		/**
		 * in case of failure, a new, default configuration is loaded
		 */
		} catch (NoSaveException e1) {
			config =new ArrayList<Object>();
			config.add(50);
			config.add(100);
			config.add(3);
			config.add(true);
			EarthDefenderConfig.write(window.userName, 50, 100, 3, true);
		}
		/**
		 * if everything goes well, the configuration is loaded
		 */
		boolean bouncers=true;
		for(Object o: config){
			if(o instanceof Boolean){
				bouncers=(Boolean)o;
			}
		}
		/**
		 * the level filler is called, the enemies, the defender and the thread are created and the thread starts
		 */
		EarthDefenderLevelFiller filler=new EarthDefenderLevelFiller(this, velEnem, velEnemY,bouncers);
		ArrayList<ArrayList<Enemy>> listaEnemigos = filler.addEnemigos();
		def=new Defender(window.width/2,window.height-120 ,this.getXScale(), this.getYScale(),this);
		this.add(def,0);
		def.setVisible(true);
		int a=(int)config.get(1);
		int b=(int)config.get(2);
		edThread=new EarthDefenderGameThread(listaEnemigos,def, this,a,b, filler);
		edThread.prob=(int) config.get(0);
		edThread.start();
		tRunning=true;	
	}
	@Override
	/**
	 * these events make the Defender halt as soon as the direction keys are released
	 */
	public void keyReleased(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_A) {
			apressed=false;
			if(!dpressed){
				def.setDX(0);
				}else{
					def.setDX(200);
				}
		}else if(e.getKeyCode() == KeyEvent.VK_D) {
			dpressed=false;
			if(!apressed){
				def.setDX(0);
				}else{
					def.setDX(-200);
				}
		}
	}

	@Override
	public void focusGained(FocusEvent e) {
		
	}

	@Override
	public void focusLost(FocusEvent e) {
		this.requestFocus();
	}
	
	public float getXScale() {
		return xScale;
	}
	
	public float getYScale() {
		return yScale;
	}
}
